/**
 * @author qiuny
 * @description 画布插件，用于控制画布属性
 * @class
 * @see {@link CoverEditor}
 */
import { fabric } from 'fabric'
import { throttle } from 'lodash-es'

class WorkspacePlugin {
    static apis = ['big', 'small', 'auto', 'one', 'setSize', 'getWorkspase', 'setWorkspaseBg'];
    static events = ['sizeChange'];
    constructor(canvas, editor) {
        this.canvas = canvas
        this.editor = editor
        this.workspaces = null
        this.workspaceEl = null
        this.options = {}
        this.init({
            width: 900,
            height: 2000,
        });
        this.zoomRatio = 0.85;
    }
    init (opt) {
        const workspaceEL = document.querySelector('#workspace')
        if (!workspaceEL) {
            throw new Error('element #workspace is missing, please check!');
        }
        this.workspaceEl = workspaceEL
        this.workspaces = null
        this.options = opt
        this._initBackground()
        this._initWorkspace()
        this._initResizeObserve()
        this._initWheel()
    }

    _initBackground() {
        this.canvas.backgroundImage = '';
        // const { left, top, width, height } = this.workspaceEl.getBoundingClientRect();
        const width = this.workspaceEl.offsetWidth;
        const height = this.workspaceEl.offsetHeight;
        this.canvas.setWidth(width);
        this.canvas.setHeight(height);
    }

    // 构建画布
    _initWorkspace() {
        const { height, width } = this.options
        const workspace = new fabric.Rect({
            // fill: 'rgba(255,255,255,1)',
            fill: '#fff',
            width,
            height,
            id: 'workspace',
            strokeWidth: 0
        })
        workspace.set({
            selectable: false,
            hasControls: false,
            hoverCursor: 'default'
        })
        this.canvas.add(workspace)
        this.canvas.renderAll()
        this.workspaces = workspace
        if (this.canvas.clearHistory) {
            this.canvas.clearHistory()
        }
        this.auto()
    }

    _initResizeObserve() {
        if (!window.ResizeObserver) {
            console.warn('Resize observer not supported! will lose the automatic change function!')
            return
        }
        const resizeObsever = new ResizeObserver(
            throttle(() => {
                this.auto()
            }, 50)
        )
        resizeObsever.observe(this.workspaceEl)
    }

    _initWheel() {}

    // 返回workspace对象
    getWorkspase() {
        return this.canvas.getObjects().find((item) => item.id === 'workspace');
    }

    setSize (width, height) {
        this._initBackground()
        this.options.width = width
        this.options.height = height
        // 重新设置workspace
        this.workspaces = this.canvas.getObjects().find((item) => item.id === 'workspace')
        this.workspaces.set({
            width: width,
            height: height
        })
        this.editor.emit('sizeChange', this.workspaces.width, this.workspaces.height)
        this.auto()
    }

    big() {
        let zoomRatio = this.canvas.getZoom()
        zoomRatio += 0.05
        const center = this.canvas.getCenter()
        this.canvas.zoomToPoint(new fabric.Point(center.left, center.top), zoomRatio)
    }

    small () {
        let zoomRatio = this.canvas.getZoom()
        zoomRatio -= 0.05
        const center = this.canvas.getCenter()
        this.canvas.zoomToPoint(
            new fabric.Point(center.left, center.top),
            zoomRatio < 0 ? 0.01 : zoomRatio
        );
    }

    setWorkspaseBg(color) {
        const workspase = this.getWorkspase();
        workspase?.set('fill', color);
    }

    getScale() {
        return fabric.util.findScaleToFit(this.getWorkspase(), {
            width: this.workspaceEl.offsetWidth,
            height: this.workspaceEl.offsetHeight,
        })
    }

    auto () {
        const scale = this.getScale()
        this.setZoomAuto(scale*this.zoomRatio)
    }

    one() {
        this.setZoomAuto(1 * this.zoomRatio);
        this.canvas.requestRenderAll();
    }

    setZoomAuto (scale, callback) {
        const { workspaceEl } = this
        const width = workspaceEl.offsetWidth;
        const height = workspaceEl.offsetHeight;
        this.canvas.setWidth(width);
        this.canvas.setHeight(height);

        const center = this.canvas.getCenter();

        this.canvas.setViewportTransform(fabric.iMatrix.concat());
        this.canvas.zoomToPoint(new fabric.Point(center.left, center.top), scale);
        if (!this.workspaces) return;
        this.setCenterFromObject(this.workspaces);

        // 超出画布不展示
        this.workspaces.clone((cloned) => {
            this.canvas.clipPath = cloned;
            this.canvas.requestRenderAll();
        });
        if (callback) callback(this.workspaces.left, this.workspaces.top);
    }

    /**
     * 设置画布中心到指定对象中心点上
     * @param {Object} obj 指定的对象
     */
    setCenterFromObject(obj) {
        const { canvas } = this;
        const objCenter = obj.getCenterPoint();
        const viewportTransform = canvas.viewportTransform;
        if (canvas.width === undefined || canvas.height === undefined || !viewportTransform) return;
        viewportTransform[4] = canvas.width / 2 - objCenter.x * viewportTransform[0];
        viewportTransform[5] = canvas.height / 2 - objCenter.y * viewportTransform[3];
        canvas.setViewportTransform(viewportTransform);
        canvas.renderAll();
    }
}

export default WorkspacePlugin;